import axios from 'axios'
import { getLocalStorageItem, setLocalStorageItem } from '../functions';
import notify from "element-ui/packages/notification";
import qs from 'qs';
import nprogress from 'nprogress';

function stringify(obj) {
    return typeof obj === 'string' ? obj : qs.stringify(obj);
}

// axios设置默认配置
// axios.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded';
// axios.defaults.baseURL = 'https://manager-mall.yusido.net';
axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? 'https://manager-mall.yusido.net' : '//';
axios.defaults.transformRequest = stringify;
axios.defaults.timeout = 8000;
axios.defaults.timeoutErrorMessage = '响应超时请重试';

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    let accessToken = getLocalStorageItem('token').access_token;

    // 如果访问令牌存在则请求头携带访问令牌
    if (accessToken && config.url !== '/yxl/oauth/token') {
        config.headers.Authorization = `bearer ${accessToken}`;
    }

    // 进度条开始
    nprogress.start();

    return config;

}, function (error) {
    // 对请求错误做些什么

    nprogress.done();

    // 错误通知
    notify.error({
        title: '错误通知',
        message: `本地发起请求错误，请检查网络连接：${error.message}`
    })

    // promise拒绝
    return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    nprogress.done();
    return response;
}, function (error) {
    // 对响应错误做点什么
    nprogress.done();
    // 错误通知
    notify.error({
        title: '错误通知',
        message: `服务器响应错误，请刷新重试。error message => ${error.message}`,
        showClose: false,
        duration: 1e4
    })

    return Promise.reject(error);
});

export default {
    install(Vue) {
        // 是否正在刷新
        let refreshing = false;
        // 保存登录失效的请求
        let requests = [];

        Vue.prototype.$request = function request(method, url, params, data, config) {
            let $this = this;

            return new Promise(function (resolve, reject) {
                axios(Object.assign({ method, url, params, data }, config)).then(function (response) {
                    let responseData = response.data;

                    // 避免响应数据字符串状态码
                    responseData.code = +responseData.code;

                    // 如果响应数据内的状态码是200则返回响应数据内的数据
                    if (responseData.code === 200) {
                        return resolve(responseData.data || responseData);
                    }

                    // 如果响应数据内的状态码是4002登录失效需要刷新token
                    if (responseData.code === 4002) {

                        // 保证并发请求只刷新一次访问令牌
                        if (!refreshing) {
                            console.log('刷新token');

                            refreshing = true;

                            // 刷新访问令牌
                            axios.post('/yxl/oauth/token', {
                                grant_type: 'refresh_token',
                                refresh_token: getLocalStorageItem('token').refresh_token,
                                client_id: 'mall_admin',
                                client_secret: 'Hgz_n2i0t@2020_mall#admin'
                            }).then(function ($response) {

                                if ($response.data.code === 200) {
                                    $this.$notify.success({
                                        title: '成功通知',
                                        message: '刷新登录状态成功',
                                    });

                                    setLocalStorageItem('token', $response.data.data);

                                    for (const request of requests) {
                                        request();
                                    }

                                    requests = [];
                                } else {
                                    $this.$notify.error({
                                        title: '错误通知',
                                        message: `刷新登录状态失败，请重新登录。`,
                                        showClose: false,
                                        duration: 1e4
                                    });
                                    setLocalStorageItem('token');
                                    // location.reload();
                                }

                            }).catch(function (errorMessage) {
                                $this.$notify.error({
                                    title: '错误通知',
                                    message: `刷新登录状态出错，请手动刷新页面重新登录。error message => ${errorMessage}`,
                                    showClose: false,
                                    duration: 1e4
                                });
                                setLocalStorageItem('token');
                            }).finally(function () {
                                refreshing = false;
                            })
                        }

                        // 保存请求配置
                        return resolve(new Promise(function ($resolve, $reject) {
                            requests.push(function () {
                                $resolve($this.$request(undefined, undefined, undefined, undefined, response.config))
                            })
                        }))
                    }

                    $this.$message.error(responseData.msg);
                }).catch(function (error) { })

            })

        }

        Vue.prototype.$post = function (url, data, config) {
            return this.$request('POST', url, null, data, config);
        }

        Vue.prototype.$put = function (url, data, config) {
            return this.$request('PUT', url, null, data, config);
        };

        Vue.prototype.$get = function (url, params, config) {
            return this.$request('GET', url, params, null, config);
        };

        Vue.prototype.$$delete = function (url, params, config) {
            return this.$request('DELETE', url, params, null, config);
        };
    }
}
